namespace Plugins.Engine
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using Plugins.Core.Interfaces;
    using Plugins.Engine.Internal;
    using Plugins.Interfaces;

    [Serializable]
    public class PluginCollectionContainer : IPluginCollectionContainer, IPluginEnumerator
    {
        private Hashtable _hosts = new Hashtable();

        public void AddHost(string name, IPluginConfiguration host)
        {
            if (name != null)
            {
                if (!this._hosts.ContainsKey(name))
                {
                    this._hosts.Add(name, host);
                }
            }
        }

        public IEnumerable<IPluginObject> GetActivePlugins(Predicate<IPluginObject> match)
        {
            IEnumerable<IPluginObject> objects = ActivePlugins;
            if (objects != null)
            {
                foreach (IPluginObject plugin in objects)
                {
                    if (match(plugin))
                    {
                        yield return plugin;
                    }
                }
            }
        }

        public IEnumerable<IPluginObject> GetLoadedPlugins(Predicate<IPluginObject> match)
        {
            IEnumerable<IPluginObject> objects = LoadedPlugins;
            if (objects != null)
            {
                foreach (IPluginObject plugin in objects)
                {
                    if (match(plugin))
                    {
                        yield return plugin;
                    }
                }
            }
        }

        public static IPluginObjectCollection GetActivePlugins(IPluginCollectionContainer container, Type type)
        {
            if (container != null)
            {
                PluginObjectCollection plugins = new PluginObjectCollection();
                IEnumerable<IPluginObject> objects = container.ActivePlugins;
                if (objects != null)
                {
                    foreach (IPluginObjectInternal plugin in objects)
                    {
                        if (plugin.InterfaceType == type)
                        {
                            plugins.Add(plugin);
                        }
                    }
                }
                return plugins;
            }
            return null;
        }

        public static IPluginObjectCollection GetLoadedPlugins(IPluginCollectionContainer container, Type type)
        {
            if (container != null)
            {
                PluginObjectCollection plugins = new PluginObjectCollection();
                IEnumerable<IPluginObject> objects = container.LoadedPlugins;
                if (objects != null)
                {
                    foreach (IPluginObjectInternal plugin in objects)
                    {
                        if (plugin.InterfaceType == type)
                        {
                            plugins.Add(plugin);
                        }
                    }
                }
                return plugins;
            }
            return null;
        }

        [SuppressMessage("Microsoft.Design", "CA1004")]
        public static IPluginObjectCollection<T> GetActivePlugins<T>(IPluginCollectionContainer container)
        {
            if (container != null)
            {
                PluginObjectCollection<T> plugins = new PluginObjectCollection<T>();
                IEnumerable<IPluginObject> objects = container.ActivePlugins;
                if (objects != null)
                {
                    foreach (IPluginObjectInternal plugin in objects)
                    {
                        if (plugin.InterfaceType == typeof(T))
                        {
                            IPluginObject<T> obj = plugin as IPluginObject<T>;
                            if (obj != null)
                            {
                                plugins.Add(obj);
                            }
                        }
                    }
                }
                return plugins;
            }
            return null;
        }

        [SuppressMessage("Microsoft.Design", "CA1004")]
        public static IPluginObjectCollection<T> GetLoadedPlugins<T>(IPluginCollectionContainer container)
        {
            if (container != null)
            {
                PluginObjectCollection<T> plugins = new PluginObjectCollection<T>();
                IEnumerable<IPluginObject> objects = container.LoadedPlugins;
                if (objects != null)
                {
                    foreach (IPluginObjectInternal plugin in objects)
                    {
                        if (plugin.InterfaceType == typeof(T))
                        {
                            IPluginObject<T> obj = plugin as IPluginObject<T>;
                            if (obj != null)
                            {
                                plugins.Add(obj);
                            }
                        }
                    }
                }
                return plugins;
            }
            return null;
        }

        public IPluginConfiguration GetHost(string hostName)
        {
            if (hostName != null)
            {
                if (this._hosts.ContainsKey(hostName))
                {
                    return (IPluginConfiguration)this._hosts[hostName];
                }
            }
            return null;
        }

        public void RemoveHost(string name, IPluginConfiguration host)
        {
            if (name != null)
            {
                if (this._hosts.ContainsKey(name))
                {
                    this._hosts.Remove(name);
                }
            }
        }

        public int Count
        {
            get
            {
                int count = 0;
                IEnumerable<IPluginConfiguration> hosts = this.Hosts;
                if (hosts != null)
                {
                    foreach (IPluginConfiguration host in hosts)
                    {
                        count += host.Count;
                    }
                }
                return count;
            }
        }

        public IEnumerable<IPluginConfiguration> Hosts
        {
            get
            {
                foreach (IPluginConfiguration host in _hosts.Values)
                {
                    yield return host;
                }
            }
        }

        public IEnumerable<IPluginObject> ActivePlugins
        {
            get
            {
                IEnumerable<IPluginConfiguration> hosts = Hosts;
                if (hosts != null)
                {
                    foreach (IPluginConfiguration host in hosts)
                    {
                        IEnumerable<IPluginObject> objects = host.ActivePlugins;
                        if (objects != null)
                        {
                            foreach (IPluginObject plugin in objects)
                            {
                                yield return plugin;
                            }
                        }
                    }
                }
            }
        }

        public IEnumerable<IPluginObject> LoadedPlugins
        {
            get
            {
                IEnumerable<IPluginConfiguration> hosts = Hosts;
                if (hosts != null)
                {
                    foreach (IPluginConfiguration host in hosts)
                    {
                        IEnumerable<IPluginObject> objects = host.LoadedPlugins;
                        if (objects != null)
                        {
                            foreach (IPluginObject plugin in objects)
                            {
                                yield return plugin;
                            }
                        }
                    }
                }
            }
        }
    }
}

